package com.engine4cloud.tdf.common.audit.handle;

import com.engine4cloud.tdf.admin.api.entity.SysAuditLog;
import com.engine4cloud.tdf.admin.api.feign.RemoteAuditLogService;
import com.engine4cloud.tdf.common.audit.annotation.Audit;
import com.engine4cloud.tdf.common.core.constant.SecurityConstants;
import com.engine4cloud.tdf.common.core.util.KeyStrResolver;
import com.engine4cloud.tdf.common.core.util.SpringContextHolder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.javers.core.Changes;
import org.javers.core.diff.Change;
import org.javers.core.diff.changetype.ValueChange;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 默认的审计日志存储
 *
 * @author tdf
 * @date 2023/2/27
 */
@Slf4j
@RequiredArgsConstructor
public class DefaultAuditLogHandle implements IAuditLogHandle {

    private final RemoteAuditLogService remoteLogService;

    private final KeyStrResolver tenantKeyStrResolver;

    @Override
    public void handle(Audit audit, Changes changes) {
        // 如果变更项为空则不进行审计
        if (changes.isEmpty()) {
            return;
        }

        // 获取当前操作人
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 如果获取不到授权信息、或者没有身份信息的接口 直接跳过处理
        if (Objects.isNull(authentication) || !authentication.isAuthenticated()) {
            return;
        }

        List<SysAuditLog> auditLogList = new ArrayList<>();
        for (Change change : changes) {
            ValueChange valueChange = (ValueChange) change;

            SysAuditLog auditLog = new SysAuditLog();
            auditLog.setAuditName(audit.name());
            auditLog.setAuditField(valueChange.getPropertyName()); // 修改的字段名称

            if (Objects.nonNull(valueChange.getLeft())) {
                auditLog.setBeforeVal(valueChange.getLeft().toString()); // 更改前的值
            }
            if (Objects.nonNull(valueChange.getRight())) {
                auditLog.setAfterVal(valueChange.getRight().toString()); // getRight
            }

            auditLog.setCreateBy(authentication.getName()); // 操作人
            auditLog.setCreateTime(LocalDateTime.now()); // 操作时间
            auditLog.setTenantId(Long.parseLong(tenantKeyStrResolver.key())); // 设置操作所属租户

            auditLogList.add(auditLog);
        }

        // 异步保存日志，提升性能
        IAuditLogHandle auditLogHandle = SpringContextHolder.getBean(IAuditLogHandle.class);
        auditLogHandle.asyncSend(auditLogList);
    }

    @Async
    public void asyncSend(List<SysAuditLog> auditLogList) {
        remoteLogService.saveLog(auditLogList, SecurityConstants.FROM_IN);
    }

}
